# Author: Liang Bing
# Email: believer19940901@gmail.com
# Phone: 15902720373

# ---------- 加载依赖 ----------
packages <- c("optparse", "ggplot2", "ggsci", "jsonlite", "pacman", "dplyr")
pacman::p_load(char = packages)

# ---------- 工具函数 ----------
`%||%` <- function(a, b) if (!is.null(a)) a else b

# ---------- 参数解析 ----------
parse.opts <- function() {
  option_list <- list(
    make_option(c("-i", "--input_csv"), type = "character", help = "输入 CSV 文件"),
    make_option(c("-c", "--config_json"), type = "character", help = "配置 JSON 文件"),
    make_option(c("-f", "--output_pdf"), type = "character", help = "输出 PDF 路径"),
    make_option(c("-g", "--output_png"), type = "character", help = "输出 PNG 路径")
  )
  parser <- OptionParser(option_list = option_list)
  opts <- parse_args(parser)
  
  # 手动校验
  required <- c("input_csv", "config_json", "output_pdf", "output_png")
  for (field in required) {
    if (is.null(opts[[field]])) {
      print_help(parser)
      stop(paste("缺少必需参数 --", field, sep = ""), call. = FALSE)
    }
  }
  return(opts)
}

data.viz <- function(opts){
  config <- fromJSON(opts$config_json)
  df <- read.csv(
    opts$input_csv, 
    fileEncoding = "utf-8", 
    stringsAsFactors = FALSE
  ) %>%
    arrange(Group, desc(Value)) %>%
    mutate(Sample = factor(Sample, level=unique(Sample)))
  p <- ggplot(df, aes(x = Sample, y = Value)) +
    geom_col(
      aes(fill=Group),
      color = config$barColor %||% "#808080",
      alpha = config$barAlpha %||% 0.9
    ) + 
    geom_text(
      aes(label = round(Value, 2)), 
      vjust = -(config$labelVjust %||% 0.5), 
      size= config$labelSize %||% 2.5, 
      color="#808080"
    ) +
    switch(
      config$barFill %||% "npg",
      npg           = scale_fill_npg(),
      aaas          = scale_fill_aaas(),
      lancet        = scale_fill_lancet(),
      jama          = scale_fill_jama(),
      nejm          = scale_fill_nejm(),
      jco           = scale_fill_jco(),
      ucscgb        = scale_fill_ucscgb(),
      IGV           = scale_fill_IGV(),
      d3            = scale_fill_d3(),
      d3_futuristic = scale_fill_d3_futuristic(),
      d3_category10 = scale_fill_d3_category10(),
      d3_category20 = scale_fill_d3_category20(),
      startrek      = scale_fill_startrek(),
      tron          = scale_fill_tron(),
      pitaya        = scale_fill_pitaya(),
      scale_fill_npg()  # 默认
    ) +
    labs(
      x = config$xTitleText %||% "X",
      y = config$yTitleText %||% "Y",
      title = config$pTitleText %||% "Example of Grouped Bar Plot",
      fill = config$lTitleText %||% "Group"
    ) +
    switch(
      config$pTheme %||% "bw",
      grey     = theme_grey(),
      bw       = theme_bw(),
      linedraw = theme_linedraw(),
      light    = theme_light(),
      dark     = theme_dark(),
      minimal  = theme_minimal(),
      classic  = theme_classic(),
      void     = theme_void(),
      test     = theme_test(),
      theme_bw()
    ) +
    theme(
      plot.title = element_text(
        family = "Times",
        size   = config$pTitleSize %||% 18,
        color  = config$pTitleColor %||% "#000000",
        face   = "bold"
      ),
      axis.title.x = element_text(
        family = "Times",
        size   = config$xTitleSize %||% 18,
        color  = config$xTitleColor %||% "#000000",
        face   = "bold"
      ),
      axis.title.y = element_text(
        family = "Times",
        size   = config$yTitleSize %||% 18,
        color  = config$yTitleColor %||% "#000000",
        face   = "bold"
      ),
      axis.text.x = element_text(
        family = "Times",
        angle = 45,
        hjust =1,
        size  = config$xTextSize %||% 14,
        color = config$xTextColor %||% "#000000"
      ),
      axis.text.y = element_text(
        family = "Times",
        size  = config$yTextSize %||% 14,
        color = config$yTextColor %||% "#000000"
      ),
      legend.title = element_text(
        family = "Times",
        face = "bold",
        size  = config$lTitleSize %||% 18,
        color = config$lTitleColor %||% "#000000"
      ),
      legend.text  = element_text(
        family = "Times",
        size  = config$lTextSize %||% 14,
        color = config$lTextColor %||% "#000000"
      ),
    )
  
  # ---------- 保存输出 ----------
  ggsave(opts$output_pdf, plot = p,
         width = config$pWidth %||% 8,
         height = config$pHeight %||% 6)
  ggsave(opts$output_png, plot = p,
         width = config$pWidth %||% 8,
         height = config$pHeight %||% 6,
         dpi = config$pDpi %||% 300)
}

# ---------- 主入口 ----------
main <- function() {
  opts <- parse.opts()
  data.viz(opts)
  quit(status = 0)
}

main()
